<!-- 定时任务管理 -->
<script setup lang="ts">
import { reactive, ref, watch, onMounted } from "vue"
import * as TaskJobApi from "@/api/taskJob"
import { type TaskJobData } from "@/api/taskJob/types/taskJob"
import { type FormInstance, type FormRules, ElMessage, ElMessageBox } from "element-plus"
import { Search, Refresh } from "@element-plus/icons-vue"
import { usePagination } from "@/hooks/usePagination"
import { cloneDeep } from "lodash-es"
import { mount } from "@vue/test-utils"
import { checkPermission } from "@/utils/permission"
import cronParser from "cron-parser"
import TaskJobLog from "@/views/taskJob/taskJobLog.vue"

defineOptions({
  // 命名当前组件
  name: "TaskJob"
})

const loading = ref<boolean>(false)
const { paginationData, handleCurrentChange, handleSizeChange } = usePagination()

//#region 增
const DEFAULT_FORM_DATA = {
  id: 0,
  name: "",
  cron: ""
}

//是否展示定时任务列表
const isExpandTask = ref(true)
// 是否展示定时任务日志table
const isExpandLog = ref(false)
const dialogVisible = ref<boolean>(false)
const formRef = ref<FormInstance | null>(null)
const formData = ref()

//#region 更新频率
const cronDialogVisible = ref<boolean>(false)
const cronFormRef = ref<FormInstance>()
const cronFormData = ref({ id: 0, name: "", cron: "" })
const cronFormRules = reactive<FormRules>({
  cron: [
    { required: true, trigger: "blur", message: "请输入cron表达式" },
    {
      validator: (rule, value, callback) => {
        // 检查输入是否为有效的 Cron 表达式
        try {
          cronParser.parseExpression(value)
          callback()
        } catch (error) {
          callback(new Error("输入的 Cron 表达式无效，请检查" + error))
        }
      },
      trigger: "blur"
    }
  ]
})

const openHandleCron = (row: TaskJobData) => {
  cronDialogVisible.value = true
  cronFormData.value = {
    id: row.id!,
    cron: row.cron,
    name: row.name
  }
}

const resetCronForm = () => {
  cronFormRef.value?.clearValidate()
  cronFormData.value = { id: 0, cron: "", name: "" }
}
const handleUpdateCron = (formEl: FormInstance | undefined) => {
  if (!formEl) return
  formEl.validate((valid: boolean, fields) => {
    if (!valid) return console.error("表单校验不通过", fields)

    loading.value = true

    TaskJobApi.modifyCronApi(cronFormData.value.id, cronFormData.value.cron)
      .then(() => {
        ElMessage.success("操作成功")
        cronDialogVisible.value = false
        getTableData()
      })
      .finally(() => {
        loading.value = false
      })
  })
}
//#endregion

const formRules = reactive<FormRules>({
  name: [{ required: true, trigger: "blur", message: "请输入任务名称" }],
  note: [{ required: true, trigger: "blur", message: "请输入备注" }]
})
const handleCreateOrUpdate = () => {
  formRef.value?.validate((valid: boolean, fields) => {
    if (!valid) return console.error("表单校验不通过", fields)
    loading.value = true

    TaskJobApi.updateTaskJobBaseDataApi(formData.value)
      .then(() => {
        ElMessage.success("操作成功")
        dialogVisible.value = false
        getTableData()
      })
      .finally(() => {
        loading.value = false
      })
  })
}

const resetForm = () => {
  formRef.value?.clearValidate()
  formData.value = cloneDeep(DEFAULT_FORM_DATA)
}
//#endregion

//#region operation
/**  运行一次 */
const runOnce = (row: TaskJobData) => {
  const id = row.id
  if (!id) return
  ElMessageBox.confirm(`确认运行一次 [${row.name}] 吗`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  }).then(() => {
    TaskJobApi.runOnceApi(id).then(() => {
      ElMessage.success("操作成功")
      getTableData()
    })
  })
}

/**  暂停 */
const pause = (row: TaskJobData) => {
  const id = row.id
  if (!id) return
  ElMessageBox.confirm(`确认暂停 [${row.name}] 吗`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  }).then(() => {
    TaskJobApi.pauseApi(id).then(() => {
      ElMessage.success("操作成功")
      getTableData()
    })
  })
}
/**  恢复 */
const resume = (row: TaskJobData) => {
  const id = row.id
  if (!id) return
  ElMessageBox.confirm(`确认恢复 [${row.name}] 吗`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  }).then(() => {
    TaskJobApi.resumeApi(id).then(() => {
      ElMessage.success("操作成功")
      getTableData()
    })
  })
}
/**注册任务*/
const register = (row: TaskJobData) => {
  const id = row.id
  if (!id) return
  ElMessageBox.confirm(`确认注册 [${row.name}] 到quartz吗`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  }).then(() => {
    TaskJobApi.registerApi(id).then(() => {
      ElMessage.success("操作成功")
      getTableData()
    })
  })
}

/** 移除*/
const remove = (row: TaskJobData) => {
  const id = row.id
  if (!id) return
  ElMessageBox.confirm(`确认移除 [${row.name}] 吗`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  }).then(() => {
    TaskJobApi.removeApi(id).then(() => {
      ElMessage.success("操作成功")
      getTableData()
    })
  })
}
//#endregion

//#region 改
const handleUpdate = (row: TaskJobData) => {
  dialogVisible.value = true
  formData.value = cloneDeep(row)
}
//#endregion

// 状态 下拉框
const statusSelectOptions = ref([
  { key: "WORKING", value: "运行" },
  { key: "PAUSE", value: "暂停" },
  { key: "REMOVE", value: "删除" }
])

//#region 查
const tableData = ref<TaskJobData[]>([])
const searchFormRef = ref<FormInstance | null>(null)
const searchData = reactive({
  name: "",
  code: "",
  status: "",
  group: ""
})

const getTableData = () => {
  loading.value = true
  TaskJobApi.getTaskJobDataApi({
    page: paginationData.currentPage,
    size: paginationData.pageSize,
    ...searchData
  })
    .then(({ data }) => {
      paginationData.total = data.total
      tableData.value = data.datas
    })
    .catch(() => {
      tableData.value = []
    })
    .finally(() => {
      loading.value = false
    })
}
const handleSearch = () => {
  paginationData.currentPage === 1 ? getTableData() : (paginationData.currentPage = 1)
}
const resetSearch = () => {
  searchFormRef.value?.resetFields()

  handleSearch()
}
onMounted(() => {})
//#endregion

/** 监听分页参数的变化 */
watch([() => paginationData.currentPage, () => paginationData.pageSize], getTableData, { immediate: true })

mount
</script>
<template>
  <div class="app-container">
    <el-card class="mt-2" shadow="hover">
      <template #header>
        <el-button
          :type="isExpandTask ? 'success' : 'primary'"
          plain
          size="small"
          @click="isExpandTask = !isExpandTask"
          :icon="isExpandTask ? 'ArrowDown' : 'ArrowRight'"
        >
          {{ isExpandTask ? "收起" : "展开" }}定时任务列表
        </el-button>
      </template>
      <template v-if="isExpandTask">
        <el-card v-loading="loading" shadow="never" class="search-wrapper">
          <el-form ref="searchFormRef" :inline="true" :model="searchData" size="small">
            <el-form-item prop="name" label="名称">
              <el-input v-model="searchData.name" placeholder="请输入" />
            </el-form-item>

            <el-form-item prop="code" label="code">
              <el-input v-model="searchData.code" placeholder="请输入" />
            </el-form-item>
            <el-form-item prop="group" label="组">
              <el-input v-model="searchData.group" placeholder="请输入" />
            </el-form-item>

            <el-form-item prop="status" label="状态">
              <el-select
                v-model="searchData.status"
                clearable
                placeholder="请选择状态"
                style="width: 200px"
                :empty-values="[null]"
              >
                <el-option v-for="item in statusSelectOptions" :key="item.key" :label="item.value" :value="item.key" />
              </el-select>
            </el-form-item>

            <el-form-item>
              <el-button type="primary" :icon="Search" @click="handleSearch">查询</el-button>
              <el-button :icon="Refresh" @click="resetSearch">重置</el-button>
            </el-form-item>
          </el-form>
        </el-card>
        <el-card v-loading="loading" shadow="never">
          <div class="table-wrapper" size="small" max-height="380">
            <el-table :data="tableData" size="small" :border="true" stripe>
              <el-table-column prop="name" label="名称" align="center" />
              <el-table-column prop="code" label="code" align="center" />
              <el-table-column prop="group" label="组" align="center" />
              <el-table-column prop="cron" label="频率" align="center" />

              <el-table-column prop="statusText" label="状态" align="center">
                <template #default="scope">
                  <el-tag v-if="scope.row.status == 'WORKING'" type="success" effect="plain" disable-transitions>{{
                    scope.row.statusText
                  }}</el-tag>
                  <el-tag v-if="scope.row.status == 'PAUSE'" type="warning" effect="plain" disable-transitions>{{
                    scope.row.statusText
                  }}</el-tag>
                  <el-tag v-if="scope.row.status == 'REMOVE'" type="danger" effect="plain" disable-transitions>{{
                    scope.row.statusText
                  }}</el-tag>
                </template>
              </el-table-column>
              <el-table-column prop="note" label="备注" header-align="center" align="left" show-overflow-tooltip />
              <el-table-column fixed="right" label="操作" width="320" align="center">
                <template #default="scope">
                  <el-button-group class="ml-2">
                    <el-button
                      type="success"
                      text
                      bg
                      size="small"
                      v-if="
                        ['WORKING', 'PAUSE'].includes(scope.row.status) && checkPermission(['admin', 'manager', 'team'])
                      "
                      @click="runOnce(scope.row)"
                      >运行一次</el-button
                    >
                    <el-button
                      type="danger"
                      text
                      bg
                      size="small"
                      v-if="
                        ['WORKING', 'PAUSE'].includes(scope.row.status) && checkPermission(['admin', 'manager', 'team'])
                      "
                      @click="remove(scope.row)"
                      >移除</el-button
                    >
                    <el-button
                      type="warning"
                      text
                      bg
                      size="small"
                      v-if="['WORKING'].includes(scope.row.status) && checkPermission(['admin', 'manager', 'team'])"
                      @click="pause(scope.row)"
                      >暂停</el-button
                    >
                    <el-button
                      type="primary"
                      text
                      bg
                      size="small"
                      v-if="['PAUSE'].includes(scope.row.status) && checkPermission(['admin', 'manager', 'team'])"
                      @click="resume(scope.row)"
                      >恢复</el-button
                    >
                    <el-button
                      type="primary"
                      text
                      bg
                      size="small"
                      v-if="['REMOVE'].includes(scope.row.status) && checkPermission(['admin', 'manager', 'team'])"
                      @click="register(scope.row)"
                      >注册</el-button
                    >
                    <el-button
                      type="primary"
                      text
                      bg
                      size="small"
                      v-if="
                        ['WORKING', 'PAUSE'].includes(scope.row.status) && checkPermission(['admin', 'manager', 'team'])
                      "
                      @click="openHandleCron(scope.row)"
                      >更改频率</el-button
                    >
                  </el-button-group>
                  <el-button type="success" text bg size="small" @click="handleUpdate(scope.row)">修改</el-button>
                </template>
              </el-table-column>
            </el-table>
          </div>
          <div class="pager-wrapper">
            <el-pagination
              background
              :layout="paginationData.layout"
              :page-sizes="paginationData.pageSizes"
              :total="paginationData.total"
              :page-size="paginationData.pageSize"
              :currentPage="paginationData.currentPage"
              @size-change="handleSizeChange"
              @current-change="handleCurrentChange"
            />
          </div>
        </el-card>
      </template>
    </el-card>

    <!-- 更改频率 start -->
    <el-dialog
      v-model="cronDialogVisible"
      :title="'管理员更新[' + `${cronFormData.name}` + ']频率'"
      @closed="resetCronForm"
      width="40%"
    >
      <el-form ref="cronFormRef" :model="cronFormData" :rules="cronFormRules" label-width="100px" label-position="left">
        <el-form-item prop="cron" label="cron表达式">
          <el-input v-model="cronFormData.cron" placeholder="请输入正确的cron表达式" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="cronDialogVisible = false">取消</el-button>
        <el-button
          type="primary"
          @click="handleUpdateCron(cronFormRef)"
          :loading="loading"
          v-if="checkPermission(['admin'])"
          >确认</el-button
        >
      </template>
    </el-dialog>
    <!-- 更改频率 end -->

    <!-- 修改 -->
    <el-dialog v-model="dialogVisible" title="修改任务基本信息" @closed="resetForm" width="40%">
      <el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" label-position="left">
        <el-form-item prop="name" label="名称">
          <el-input v-model="formData.name" placeholder="请输入" />
        </el-form-item>

        <el-form-item prop="note" label="备注">
          <el-input v-model="formData.note" style="width: 100%" :rows="4" type="textarea" placeholder="请输入备注" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="handleCreateOrUpdate" :loading="loading" v-if="checkPermission(['admin'])"
          >确认</el-button
        >
      </template>
    </el-dialog>

    <el-card class="mt-2" shadow="hover">
      <template #header>
        <el-button
          :type="isExpandLog ? 'success' : 'primary'"
          plain
          size="small"
          @click="isExpandLog = !isExpandLog"
          :icon="isExpandLog ? 'ArrowDown' : 'ArrowRight'"
        >
          {{ isExpandLog ? "收起" : "展开" }}定时任务日志
        </el-button>
      </template>
      <template v-if="isExpandLog">
        <TaskJobLog />
      </template>
    </el-card>
  </div>
</template>

<style lang="scss" scoped>
.search-wrapper {
  margin-bottom: 20px;

  :deep(.el-card__body) {
    padding-bottom: 2px;
  }
}

.toolbar-wrapper {
  display: flex;
  justify-content: space-between;
  margin-bottom: 20px;
}

.table-wrapper {
  margin-bottom: 20px;
}

.pager-wrapper {
  display: flex;
  justify-content: flex-end;
}
</style>
